#include "Application.h"
#include "MainState.h"
#include "Observer.h"
#include "RenderWindow.h"
#include "HGEWindow.h"
#include "GeneticsEngine.h"
#include "kf_log.h"
#include "Track.h"

Application* Singleton<Application>::m_pInstance = NULL;
std::auto_ptr<Application> Application::s_pApplication;

Application::Application()
: m_pStateManager(NULL)
, m_pResourceManager(NULL)
, m_pHGE(NULL)
, m_pWindow(NULL)
{
	
}
Application::~Application()
{
}

bool Application::Setup(char* a_pWindowName, int a_width, int a_height)
{
	m_width = a_width;
	m_height = a_height;

	std::auto_ptr<Application> temp(new Application);
	s_pApplication = temp;

	s_pApplication.reset(this);
	// Here we use global pointer to HGE interface.
	// Instead you may use hgeCreate() every
	// time you need access to HGE. Just be sure to
	// have a corresponding hge->Release()
	// for each call to hgeCreate()
	m_pHGE = hgeCreate(HGE_VERSION);

	// Set our frame function
	m_pHGE->System_SetState(HGE_FRAMEFUNC, this->FrameFunc);
	m_pHGE->System_SetState(HGE_RENDERFUNC, this->RenderFunc);

    m_pHGE->System_SetState(HGE_SHOWSPLASH, false);

	//Show the mouse
    m_pHGE->System_SetState(HGE_HIDEMOUSE, false);

	// Run in windowed mode
	m_pHGE->System_SetState(HGE_WINDOWED, true);

	m_pHGE->System_SetState(HGE_USESOUND, true);

	m_pHGE->System_SetState(HGE_FPS, 60);

    m_pHGE->System_SetState(HGE_SCREENBPP, 32);

	//Set the log file
	m_pHGE->System_SetState(HGE_LOGFILE, "media/HgeLog.txt");

	//Setup the resource manager
	m_pResourceManager = new hgeResourceManager("media/resource.res");

	//Create and register the state manager
	StateManager* pStateManager = new StateManager();
	this->RegisterStateManager(pStateManager);

	m_pWindow = new RenderWindow();
	m_pWindow->Setup("The Immortal Car", 800, 600, NULL);
	HWND parent = m_pWindow->GetHGEWindow()->GetWindow();
	m_pHGE->System_SetState(HGE_HWNDPARENT, parent);

	kf::Log::getDefault().addFile("media/DebugOutput.txt");
	
	return true;
}

bool Application::Initialize()
{
	// Tries to initiate HGE with the states set.
	// If something goes wrong, "false" is returned
	// and more specific description of what have
	// happened can be read with System_GetErrorMessage().
	if(m_pHGE->System_Initiate())
	{
		return true;
	}
	else
	{	
		// If HGE initialization failed show error message
		MessageBox(NULL, m_pHGE->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
		return false;
	}
}

void Application::Execute()
{
	//Attempt to init hge
	if(Initialize())
	{
		//Chuck on our first state
		MainState* pState = new MainState();
		m_pStateManager->PushState(pState);

		while(true)
		{
			MSG msg;
			float dt = m_pWindow->GetDeltaTime();
			//Update the windows
			m_pWindow->Update();
      // Update the current state
      m_pStateManager->Update(dt);

			//Start hge game loop
			if(m_pHGE->System_GetState(HGE_HWND))
			{
				m_pHGE->System_Start();
			}
			if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
				if(msg.message == WM_QUIT)
				{
					break;
				}
			}
		}
	}

	Cleanup();

	return;
}

void Application::Cleanup()
{
	if(m_pStateManager)
	{
		delete m_pStateManager;
		m_pStateManager = NULL;
	}
	// Restore video mode and free
	// all allocated resources
	if(m_pHGE)
		m_pHGE->System_Shutdown();

	// Release the HGE interface.
	// If there are no more references,
	// the HGE object will be deleted.
	if(m_pHGE)
		m_pHGE->Release();

	//Release the auto ptr
	s_pApplication.release();
}
bool Application::FrameFunc()
{
	//Update on state manager
	Application* pApp = s_pApplication.get();
	
	//Update the observer
	Observer::GetInstance().Update();

	if(!s_pApplication.get()->m_pStateManager->GetCurrentState()->Update(s_pApplication.get()->GetHGE()->Timer_GetDelta()))
		return true;

	if(pApp->GetHGE()->Input_GetKeyState(HGEK_ESCAPE))
	{
		//ready to shutdown, return true
		return true;
	} 

	//Not ready to shutdown, return false
	return false;
}
bool Application::RenderFunc()
{
	//Render on state manager
	Application* pApp = s_pApplication.get();
	s_pApplication.get()->m_pStateManager->GetCurrentState()->Render(s_pApplication.get()->GetHGE()->Timer_GetDelta());
	//Not ready to shutdown, return false
	return false;
}
void Application::RegisterStateManager(StateManager* a_pStateManager)
{
	m_pStateManager = a_pStateManager;
}
HGE* Application::GetHGE() const
{
	return m_pHGE;
}
StateManager* Application::GetStateManager() const
{
	return m_pStateManager;
}
hgeResourceManager* Application::GetResourceManager() const
{
	return m_pResourceManager;
}
GeneticsEngine* Application::GetGeneticsEngine() const
{
  MainState* state = (MainState*)m_pStateManager->GetCurrentState();
  return state->GetGeneticsEngine();
}
RenderWindow* Application::GetWindow() const
{
	return m_pWindow;
}
int Application::GetWidth() const
{
	return m_width;
}
int Application::GetHeight() const
{
	return m_height;
}